package es.us.lsi.daw.servicios;

import java.util.Calendar;
import java.util.List;

import org.apache.commons.lang.math.NumberUtils;
import org.hibernate.criterion.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;

import es.us.lsi.daw.dao.DAOPaginacion;
import es.us.lsi.daw.dao.impl.DAOComunImpl;
import es.us.lsi.daw.model.security.User;
import es.us.lsi.daw.model.util.BaseEntity;
import es.us.lsi.daw.util.Acronimo;

public class Paginacion {

	private static Calendar			cldFin;
	private static Calendar			cldInicio;

	static {
		// Se pone la fecha de la semana anterior
		cldFin = Calendar.getInstance();
		cldInicio = (Calendar) cldFin.clone();
		cldInicio.set(Calendar.DATE, cldInicio.get(Calendar.DATE) - 7);
	}

	@Autowired
	DAOPaginacion					daoPaginacion;

	/****************************************************************************************************************/
	/****************************************** MÉTODOS GENERALES ***************************************************/
	/****************************************************************************************************************/

	public <T extends BaseEntity> ModelMap paginacion(String pagina, Class<T> clase) {

		return paginacion(pagina, clase, null);
	}

	public <T extends BaseEntity> ModelMap paginacion(String pagina, Class<T> clase, String lista) {

		return paginacion(pagina, clase, lista, null);
	}

	/**
	 * Permite paginar una lista de objetos de una determinada clase recibida por parámetro.
	 * 
	 * @param pagina
	 *            : pagina a mostrar.
	 * @param clase
	 *            : indica la clase de los objetos a listar.
	 * @return: devuelve un mapa de objetos con el listado y el número de paginas totales, asi como la página actual.
	 */
	public <T extends BaseEntity> ModelMap paginacion(String pagina, Class<T> clase, String lista, Integer numMaxRegistros) {

		ModelMap map = new ModelMap();
		String nombreLista = Acronimo.LIST + clase.getSimpleName().substring(0, 1).toUpperCase() + clase.getSimpleName().substring(1).toLowerCase();
		long numPagina;
		long totalPages;
		List<T> lstElementos = null;

		if (pagina == null || pagina.equals("") || pagina.equals("0") || !NumberUtils.isDigits(pagina))
			numPagina = 1;
		else
			numPagina = Integer.parseInt(pagina);

		long i;
		long tam;

		tam = daoPaginacion.getSizeClase(clase);

		if (numMaxRegistros == null)
			numMaxRegistros = DAOComunImpl.PAGE_SIZE;
		i = tam / numMaxRegistros;
		if (tam % numMaxRegistros != 0)
			i++;
		totalPages = i;
		if (numPagina > totalPages)
			numPagina = totalPages;
		if (numPagina < 1)
			numPagina = 1;
		lstElementos = daoPaginacion.getListaClasePaginacion(clase, numPagina, lista, numMaxRegistros);
		map.put(nombreLista, lstElementos);
		map.put("totalPages", totalPages);
		map.put("pagina", numPagina);
		map.put("registrosTotales", tam);
		map.put("registrosMostrados", lstElementos.size());

		return map;
	}

	public <T extends BaseEntity> ModelMap paginacionConOrden(Class<T> clase, String pagina, String atributo) {

		ModelMap map = new ModelMap();
		String nombreLista = Acronimo.LIST + clase.getSimpleName().substring(0, 1).toUpperCase() + clase.getSimpleName().substring(1).toLowerCase();
		long numPagina;
		long totalPages;
		List<T> lstElementos = null;

		if (pagina == null || pagina.equals("") || pagina.equals("0") || !NumberUtils.isDigits(pagina))
			numPagina = 1;
		else
			numPagina = Integer.parseInt(pagina);

		long i;
		long tam;

		tam = daoPaginacion.getSizeClase(clase);

		i = tam / DAOComunImpl.PAGE_SIZE;
		if (tam % DAOComunImpl.PAGE_SIZE != 0)
			i++;
		totalPages = i;
		if (numPagina > totalPages)
			numPagina = totalPages;
		if (numPagina < 1)
			numPagina = 1;

		lstElementos = daoPaginacion.getListaClasePaginacionOrdenada(clase, numPagina, atributo);
		map.put(nombreLista, lstElementos);
		map.put("totalPages", totalPages);
		map.put("pagina", numPagina);
		map.put("registrosTotales", tam);
		map.put("registrosMostrados", lstElementos.size());

		return map;
	}

	public ModelMap paginacionFiltroGenerico(String pagina, Object filtro, String atributo) {

		return paginacionFiltroGenerico(pagina, filtro, atributo, null, null, null);
	}

	public ModelMap paginacionFiltroGenerico(String pagina, Object filtro, String atributo, Order orden) {

		return paginacionFiltroGenerico(pagina, filtro, atributo, orden, null, null);
	}

	public ModelMap paginacionFiltroGenerico(String pagina, Object filtro, String atributo, Class<?> claseCriteria) {

		return paginacionFiltroGenerico(pagina, filtro, atributo, null, claseCriteria, null);
	}

	public ModelMap paginacionFiltroGenerico(String pagina, Object filtro, String atributo, Class<?> claseCriteria, Integer numMaxRegistros) {

		return paginacionFiltroGenerico(pagina, filtro, atributo, null, claseCriteria, numMaxRegistros);
	}

	public ModelMap paginacionFiltroGenerico(String pagina, Object filtro, String atributo, Order orden, Class<?> claseCriteria, Integer numMaxRegistros) {

		long numPagina = 0;
		if (pagina == null || pagina.equals("") || pagina.equals("0") || !NumberUtils.isDigits(pagina)) {
			numPagina = 1;
		} else {
			numPagina = Integer.parseInt(pagina);
		}
		return daoPaginacion.filtroGenerico(filtro, numPagina, atributo, orden, claseCriteria, numMaxRegistros);
	}

	public ModelMap paginacionUsuariosFiltro(String pagina, Integer numMaxRegistros, String nombre, String apellidos) {

		ModelMap map = new ModelMap();
		String nombreLista = Acronimo.LIST + "User";
		long numPagina;
		long totalPages;
		List<?> lstElementos = null;

		if (pagina == null || pagina.equals("") || pagina.equals("0") || !NumberUtils.isDigits(pagina)) {
			numPagina = 1;
		} else {
			try {
				numPagina = Integer.parseInt(pagina);
			} catch (NumberFormatException e) {
				numPagina = 1;
				e.printStackTrace();
			}
		}

		long i;
		long tam;

		tam = daoPaginacion.obtenerTamFiltroListUser(nombre, apellidos);

		if (numMaxRegistros == null) {
			numMaxRegistros = DAOComunImpl.PAGE_SIZE;
		}
		i = tam / numMaxRegistros;
		if (tam % numMaxRegistros != 0) {
			i++;
		}
		totalPages = i;

		if (numPagina > totalPages) {
			numPagina = totalPages;
		}
		if (numPagina < 1) {
			numPagina = 1;
		}
		lstElementos = daoPaginacion.filtrarListUser(nombre, apellidos, numPagina, numMaxRegistros);
		map.put(nombreLista, lstElementos);
		map.put("totalPages", totalPages);
		map.put("pagina", numPagina);
		map.put("registrosTotales", tam);
		map.put("registrosMostrados", lstElementos.size());

		return map;
	}

	public ModelMap paginacionUsuarios(String pagina, Class<User> clase, String lista, Integer numMaxRegistros) {
		ModelMap map = new ModelMap();
		String nombreLista = Acronimo.LIST + clase.getSimpleName().substring(0, 1).toUpperCase() + clase.getSimpleName().substring(1).toLowerCase();
		long numPagina;
		long totalPages;
		List<?> lstElementos = null;

		if (pagina == null || pagina.equals("") || pagina.equals("0") || !NumberUtils.isDigits(pagina))
			numPagina = 1;
		else
			numPagina = Integer.parseInt(pagina);

		long i;
		long tam;

		tam = daoPaginacion.getSizeUser(clase);

		if (numMaxRegistros == null)
			numMaxRegistros = DAOComunImpl.PAGE_SIZE;
		i = tam / numMaxRegistros;
		if (tam % numMaxRegistros != 0)
			i++;
		totalPages = i;
		if (numPagina > totalPages)
			numPagina = totalPages;
		if (numPagina < 1)
			numPagina = 1;
		lstElementos = daoPaginacion.getListaClasePaginacionUser(clase, numPagina, lista, numMaxRegistros);
		map.put(nombreLista, lstElementos);
		map.put("totalPages", totalPages);
		map.put("pagina", numPagina);
		map.put("registrosTotales", tam);
		map.put("registrosMostrados", lstElementos.size());

		return map;
	}

}
